﻿using System;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;

namespace UtilZ.Dotnet.Ex.Log
{
    /// <summary>
    /// 日志信息类
    /// </summary>
    public class LogItem
    {
        private static ConcurrentBag<LogItem> _pool;
        static LogItem()
        {
            _pool = new ConcurrentBag<LogItem>();

            //默认初始化100个对象
            for (int i = 0; i < 100; i++)
            {
                _pool.Add(new LogItem());
            }
        }

        /// <summary>
        /// 从池中获取一个对象
        /// </summary>
        /// <returns></returns>
        public static LogItem Take()
        {
            LogItem item;
            try
            {
                if (_pool.TryTake(out item))
                {
                    item.ResetRef();
                    return item;
                }
                else
                {
                    return new LogItem();
                }
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog(null, ex);
                return new LogItem();
            }
        }

        /// <summary>
        /// 将对象添加到池
        /// </summary>
        /// <param name="item"></param>
        public static void Add(LogItem item)
        {
            if (item.DecrementRef())
            {
                try
                {
                    _pool.Add(item);
                }
                catch (Exception ex)
                {
                    LogSysInnerLog.OnRaiseLog(null, ex);
                }
            }
        }







        private int _refCount = 0;

        /// <summary>
        /// 重置引用计数
        /// </summary>
        private void ResetRef()
        {
            Interlocked.Exchange(ref this._refCount, 1);
        }

        /// <summary>
        /// 减少一个引用计数
        /// </summary>
        private bool DecrementRef()
        {
            return Interlocked.Decrement(ref this._refCount) <= 0;
        }

        /// <summary>
        /// 增加一个引用计数
        /// </summary>
        public void IncrementRef()
        {
            Interlocked.Increment(ref this._refCount);
        }





        private string _logerName = null;
        /// <summary>
        /// 日志记录器名称
        /// </summary>
        public string LogerName
        {
            get { return _logerName; }
            set { _logerName = value; }
        }





        /// <summary>
        /// 构造函数
        /// </summary>
        public LogItem()
        {

        }


        #region 属性

        private DateTime _time = default(DateTime);
        /// <summary>
        /// 时间
        /// </summary>
        public DateTime Time
        {
            get { return _time; }
        }

        private int _threadID = 0;
        /// <summary>
        /// 线程ID
        /// </summary>
        public int ThreadID
        {
            get { return _threadID; }
        }

        private string _threadName = null;
        /// <summary>
        /// 线程名称
        /// </summary>
        public string ThreadName
        {
            get { return _threadName; }
        }


        private int _eventID = LogConstant.DEFAULT_EVENT_ID;
        /// <summary>
        /// 事件ID
        /// </summary>
        public int EventID
        {
            get { return _eventID; }
        }

        private object _tag = null;
        /// <summary>
        /// 与对象关联的用户定义数据
        /// </summary>
        public object Tag
        {
            get { return _tag; }
        }

        private LogLevel _level = LogLevel.Off;
        /// <summary>
        /// 日志级别
        /// </summary>
        public LogLevel Level
        {
            get { return _level; }
        }


        private string _message = null;
        /// <summary>
        /// 日志信息
        /// </summary>
        public string Message
        {
            get { return _message; }
        }

        private Exception _exception = null;
        /// <summary>
        /// 异常信息
        /// </summary>
        public Exception Exception
        {
            get { return _exception; }
        }

        /// <summary>
        /// 判断是否有堆栈信息,有返回true,没有返回false
        /// </summary>
        public bool HasStackTraceInfo
        {
            get
            {
                return !string.IsNullOrWhiteSpace(this._stackTraceInfo);
            }
        }

        private string _stackTraceInfo = null;
        /// <summary>
        /// 堆栈信息
        /// </summary>
        public string StackTraceInfo
        {
            get { return _stackTraceInfo; }
        }

        private string _content = null;
        /// <summary>
        /// 日志内容
        /// </summary>
        public string Content
        {
            get { return _content; }
        }

        #endregion





        /// <summary>
        /// 设置日志信息
        /// </summary>
        /// <param name="filePath">文件</param>
        /// <param name="lineNum">行号</param>
        /// <param name="memberName">成员名</param>
        /// <param name="time">构造函数</param>
        /// <param name="thread">线程</param>
        /// <param name="level">日志级别</param>
        /// <param name="eventId">事件ID</param>
        /// <param name="ex">异常信息</param>
        /// <param name="message">日志消息</param>
        /// <param name="tag">与对象关联的用户定义数据</param>
        public void Set(string filePath, int lineNum, string memberName, DateTime time, Thread thread,
            LogLevel level, int eventId, Exception ex, string message, object tag)
        {
#if NET4_0
            System.Runtime.CompilerServices.CallerHelper.GetCallerFeature(out filePath, out lineNum, out memberName);
#endif

            this._time = time;
            this._threadID = thread.ManagedThreadId;
            this._threadName = thread.Name;
            this._eventID = eventId;
            this._tag = tag;
            this._level = level;
            this._exception = ex;

            //日志处理
            if (ex != null && ex.StackTrace != null)
            {
                this._stackTraceInfo = ex.StackTrace;
            }
            else
            {
                this._stackTraceInfo = string.Format(@"   在位置 {0}:行号 {1} {2}", filePath, lineNum, memberName);
            }
            this._message = message;

            if (ex == null)
            {
                this._content = message;
            }
            else
            {
                StringBuilder sbContent = new StringBuilder();
                if (message != null)
                {
                    sbContent.Append(message);

                    if (sbContent.Length > 0)
                    {
                        sbContent.Append("。");
                    }
                }

                Exception innerEx = ex;
                while (innerEx != null)
                {
                    sbContent.Append(innerEx.Message);
                    innerEx = innerEx.InnerException;
                    if (innerEx != null)
                    {
                        sbContent.Append(" ---> ");
                    }
                }

                this._content = sbContent.ToString();
            }
        }





        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>String</returns>
        public override string ToString()
        {
            return this._content;
        }
    }
}
